package variabilitysmelldetection.plugin.popup.actions;

import java.util.List;

import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionDelegate;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;

import variabilitysmelldetection.measurement.Measurement;
import variabilitysmelldetection.measurement.measures.Measure;
import variabilitysmelldetection.measurement.models.ComponentItem;
import variabilitysmelldetection.measurement.models.MethodItem;
import variabilitysmelldetection.measurement.models.Project;
import variabilitysmelldetection.plugin.models.ComponentModel;
import variabilitysmelldetection.plugin.models.ItemModel;
import variabilitysmelldetection.plugin.models.OperationModel;
import variabilitysmelldetection.plugin.views.MeasuresView;
import de.ovgu.featureide.ahead.AheadComposer;
import de.ovgu.featureide.core.CorePlugin;
import de.ovgu.featureide.core.IFeatureProject;

public class MeasureAction implements IObjectActionDelegate {

	@SuppressWarnings("unused")
	private Shell shell;

	/**
	 * Constructor for Action1.
	 */
	public MeasureAction() {
		super();
	}

	/**
	 * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
	 */
	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
		shell = targetPart.getSite().getShell();
	}

	/**
	 * @see IActionDelegate#run(IAction)
	 */
	public void run(IAction action) {
		ISelection selection = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection();

		try {
			MeasuresView view = (MeasuresView) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(MeasuresView.ID);

			if ((!selection.isEmpty()) && (selection instanceof IStructuredSelection)) {
				Object obj = ((IStructuredSelection) selection).getFirstElement();
				IResource res = null;

				if (obj instanceof IResource) {
					res = (IResource)obj;
				}else if (obj instanceof IJavaProject) {
					IJavaProject javaProject = (IJavaProject) obj;
					res = javaProject.getResource();				
				}

				IFeatureProject project = CorePlugin.getFeatureProject(res);				
				if (project != null && project.getComposerID().equals(AheadComposer.COMPOSER_ID)) {
					exec(project, view);
				}
			}
		} catch (PartInitException e) {
			e.printStackTrace();
		}
	}

	private void exec(IFeatureProject featureProject, MeasuresView view){
		Project project = new Project(featureProject);

		Measurement measurement = new Measurement(project);
		measurement.execute();

		ItemModel root = new ItemModel(project.getName(), null);

		// montando medidas dos metodos
		for (Measure measure : Measurement.getMethodMeasures()) {
			ItemModel measureItem = new ItemModel(measure.getName(), root);
			double measureValue = 0;

			for (String feature : project.getFeaturesNames()) {
				ItemModel featureItem = new ItemModel(feature, measureItem);
				double featureValue = 0;

				List<ComponentItem> componentItems = project.getClassItems();
				for (ComponentItem c : componentItems) {
					if (c.getParentName().equals(feature)) {
						ComponentModel classItem = new ComponentModel(c.getName(), featureItem);
						classItem.setRefinement(c.isRefinement());
						List<MethodItem> methodItems = c.getMethods();
						double classMeasureValue = 0;

						for (MethodItem m : methodItems) {
							Measure methodMeasure = m.getMeasure(measure.getClass());
							OperationModel methodItem = new OperationModel(m.getName(), classItem);
							methodItem.setValue(methodMeasure.getValue());
							methodItem.setRefinement(m.isRefinement());

							classItem.addChild(methodItem);
							classMeasureValue += methodMeasure.getValue();
						}
						classItem.setValue(classMeasureValue);
						featureItem.addChild(classItem);
						featureValue += classMeasureValue;
					}
				}
				featureItem.setValue(featureValue);
				measureValue += featureValue;
				measureItem.addChild(featureItem);
			}
			measureItem.setValue(measureValue);			
			root.addChild(measureItem);
		}

		// montando medidas das classes
		for (Measure measure : Measurement.getComponentMeasures()) {
			ItemModel measureItem = new ItemModel(measure.getName(), root);
			double measureValue = 0;

			for (String feature : project.getFeaturesNames()) {
				ItemModel featureItem = new ItemModel(feature, measureItem);
				double featureValue = 0;

				List<ComponentItem> componentItems = project.getClassItems();
				for (ComponentItem c : componentItems) {
					if (c.getParentName().equals(feature)) {
						ComponentModel classItem = new ComponentModel(c.getName(), featureItem);
						Measure classMeasure = c.getMeasure(measure.getClass());
						classItem.setValue(classMeasure.getValue());
						classItem.setRefinement(c.isRefinement());

						featureItem.addChild(classItem);
						featureValue += classMeasure.getValue();
					}
					featureItem.setValue(featureValue);
				}
				measureItem.addChild(featureItem);
				measureValue += featureValue;
			}
			measureItem.setValue(measureValue);
			root.addChild(measureItem);
		}

		// montando medidas do projeto
		for (Measure measure : measurement.getProjectMeasures()) {
			ItemModel measureItem = new ItemModel(measure.getName(), root);

			Measure projectMeasure = project.getMeasure(measure.getClass());

			measureItem.setValue(projectMeasure.getValue());
			root.addChild(measureItem);
		}

		view.show(project, root);
	}

	/**
	 * @see IActionDelegate#selectionChanged(IAction, ISelection)
	 */
	public void selectionChanged(IAction action, ISelection selection) {
	}

}
